﻿#include "widget.h"
#include "./ui_widget.h"

#include <QDebug>
#include <QMetaType>
#include <QTimer>
#include <QVector>

#include <filesystem>
#include <iostream>
#include <string>

Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 注册
    qRegisterMetaType<QVector<QVector<double>>>("QVector<QVector<double>>");

    for (int var = 0; var < 8; ++var)
    {
        ui->widget->addGraph();
        ui->widget->graph(var)->setPen(channel_color_list_[var]);
    }

    ui->widget->xAxis->setRange(0, 1000);
    ui->widget->yAxis->setRange(-5, 5);
    ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectAxes);

    timer_ = new QTimer();
    connect(timer_, &QTimer::timeout, this, &Widget::ProcessData);

    // Windows 环境下将动态库拷贝到当前目录下
    // Linux 环境下需要手动将动态库添加到环境变量中
#ifdef WIN32
    try
    {
        // 获取当前可执行文件所在目录
        std::filesystem::path base_dir = std::filesystem::current_path();

        // 根据是否为 64 位进程设置 DLL 目录
        bool is_64_bit = (sizeof(void *) == 8);
        std::filesystem::path dll_dir;
        if (is_64_bit)
        {
            dll_dir = base_dir / "..\\..\\..\\..\\lib\\Windows\\libdaq\\lib\\x64\\msvc2019";
        }
        else
        {
            dll_dir = base_dir / "..\\..\\..\\..\\lib\\Windows\\libdaq\\lib\\x86\\msvc2019";
        }

        // 检查源目录是否存在
        if (!std::filesystem::exists(dll_dir) || !std::filesystem::is_directory(dll_dir))
        {
            std::cout << "Source directory does not exist." << std::endl;
        }

        // 构建源 DLL 路径和目标 DLL 路径
        std::string source_dll_name = "libdaq-2.0.0.dll";
        std::filesystem::path source_dll_path = dll_dir / source_dll_name;
        std::filesystem::path dest_dll_path = base_dir / source_dll_name;

        // 复制动态库到编译目录
        std::filesystem::copy_file(source_dll_path, dest_dll_path, std::filesystem::copy_options::overwrite_existing);
        std::cout << "Copied " << dll_dir.string() << " to " << base_dir.string() << std::endl;
    }
    catch (const std::filesystem::filesystem_error &ex)
    {
        std::cout << "Failed to copy DLL: " << ex.what() << std::endl;
    }
#endif

    daq331m_ = (daq331m_ptr)malloc(sizeof(daq331m_t));
    memset(daq331m_, 0, sizeof(daq331m_t));
    if (!daq331m_init(daq331m_))
    {
        qDebug() << u8"未找到动态库";
    }
}

Widget::~Widget()
{
    daq331m_deinit(daq331m_);
    free(daq331m_);
    delete ui;
}

void Widget::ProcessData()
{
    auto enable_channel_size = daq331m_->get_adc_enable_channel_size(daq331m_);
    auto storage_depth = daq331m_->get_current_sample_rate(daq331m_) / enable_channel_size;
    auto legal_channel_size = daq331m_->get_adc_legal_channel_size(daq331m_);
    QVector<QVector<double>> receive_data(legal_channel_size);
    for (uint32_t var = 0; var < receive_data.size(); ++var)
    {
        receive_data[var].resize(storage_depth);
    }

    // 判断当前数据是否已经满足读取的条件
    if (!daq331m_->adc_data_is_ready(daq331m_, storage_depth))
    {
        return;
    }

    auto read_result = true;
    for (uint32_t channel = 0; channel < legal_channel_size; channel++)
    {

        // 判断通道是否开启
        if (!(channel_state & (1 << channel)))
        {
            continue;
        }

        // 读取数据
        read_result = daq331m_->try_read_adc_data(daq331m_, channel, receive_data[channel].data(),
                                                  receive_data[channel].size(), 1000);

        if (!read_result)
        {
            qDebug() << "Error";
        }
    }

    QVector<double> x_data(storage_depth);
    for (uint32_t var = 0; var < storage_depth; ++var)
    {
        x_data[var] = 1000.0 / storage_depth * var;
    }

    if (read_result)
    {
        for (uint32_t var = 0; var < legal_channel_size; ++var)
        {
            ui->widget->graph(var)->setData(x_data, receive_data[var]);
        }
        ui->widget->replot(QCustomPlot::rpQueuedReplot);
    }
}

void Widget::on_ConnectPushButton_clicked()
{
    daq331m_->delete_device(daq331m_);
    daq331m_->create_device(daq331m_);

#if defined(USE_RS485) && !defined(USE_TCP_CLIENT) && !defined(USE_MODBUS)
    daq331m_->use_serial_backend(daq331m_, R"(\\.\COM20)", 115200);
#elif defined(USE_TCP_CLIENT) && !defined(USE_RS485) && !defined(USE_MODBUS)
    daq331m_->use_tcp_client_backend(daq331m_, "192.168.1.100", 8000);
#elif defined(USE_MODBUS) && !defined(USE_RS485) && !defined(USE_TCP_CLIENT)
    daq331m_->use_modbus_backend(daq331m_, R"(\\.\COM20)", 115200, 1);
#endif

    // 初始化一个DAQ设备
    if (!daq331m_->initialize_device(daq331m_))
    {
        qDebug() << (u8"libdaq初始化设备失败");
    }

    // 连接一个DAQ设备
    if (!daq331m_->connected_device(daq331m_))
    {
        qDebug(u8"libdaq连接设备失败");
    }

    // TCP模式下最大可以配置采样率为100k，电压为15V
    // 串口模式下最大可以配置采样率为500，电压为15V
    // Modbus模式下最大可以配置采样率为80，电压为15V
    auto voltage_range = Voltage15V;
    auto sample_rate = SampleRate1K;
#if defined(USE_RS485) && !defined(USE_TCP_CLIENT) && !defined(USE_MODBUS)
    sample_rate = SampleRate1K;
#elif defined(USE_TCP_CLIENT) && !defined(USE_RS485) && !defined(USE_MODBUS)
    sample_rate = SampleRate100K;
#elif defined(USE_MODBUS) && !defined(USE_RS485) && !defined(USE_TCP_CLIENT)
    sample_rate = SampleRate80;
#endif
    if (!daq331m_->configure_adc_parameters(daq331m_, sample_rate, voltage_range))
    {
        qDebug(u8"配置DAQ331M采样率与电压失败");
    }
    channel_state = 0b11111111; // 修改通道
    if (!daq331m_->configure_adc_channel(daq331m_, channel_state))
    {
        qDebug(u8"配置DAQ331M通道失败");
    }
}

void Widget::on_StartPushButton_clicked()
{
    timer_->setInterval(900);
    timer_->start();
    if (daq331m_->start_collection(daq331m_))
    {
        qDebug() << u8"DAQ331M开始采集数据";
    }
}

void Widget::on_StopPushButton_clicked()
{
    // 停止采集
    if (daq331m_->stop_collection(daq331m_))
    {
        qDebug() << u8"DAQ331M停止采集数据";
    }
    timer_->stop();
}
